#ifndef DISH_H_
#define DISH_H_

#include <stdbool.h>

typedef struct Dish_t *Dish;

typedef enum {
  DISH_SUCCESS,
  DISH_INVALID_ARGUMENT,
  DISH_OUT_OF_MEMORY
} DishResult;

typedef enum {
  ENTREE,
  MAIN_COURSE,
  DESERT,
  DISH_NUM_OF_TYPES //this is an invalid value
} DishType;

/**
 * Create a new dish
 * @param name The name of the new dish
 * @param dishType The type of the new dish
 * @param sweetness The sweetness of the new dish
 * @param sourness The sourness of the new dish
 * @param saltiness The saltiness of the new dish
 * @param result pointer to put error codes in. (ignore it in case of NULL).
 * value of *result:
 * DISH_INVALID_ARGUMENT if one of the other parameters has invalid value
 * DISH_OUT_OF_MEMORY if a memory allocation failed
 * DISH_SUCCESS otherwise
 * @return
 * NULL in case of error.
 * A new Dish in case of success.
 */
Dish dishCreate(const char *name, DishType dishType,
		int sweetness, int sourness, int saltiness, DishResult *result);

/**
 * Create copy of an existing Dish.
 * @param dish The dish to clone
 * @param result pointer to put error codes in. (ignore it in case of NULL).
 * value of *result:
 * DISH_INVALID_ARGUMENT if dish is NULL
 * DISH_OUT_OF_MEMORY if a memory allocation failed
 * DISH_SUCCESS otherwise
 * @return
 * NULL in case of error.
 * A new Dish (clone of dish) in case of success.
 */
Dish dishCopy(Dish dish, DishResult *result);

/**
 * Destroy a Dish.
 * @param dish The Dish to destroy. (do nothing if it's NULL)
 */
void dishDestroy(Dish dish);

/**
 * Returns the name of dish.
 * @param dish The dish whose name is returned
 * @return
 * NULL if dish is NULL
 * The name of dish, if it's a valid Dish.
 * (Note that the actual name is returned, so it will be
 * invalid after destroying dish)
 */
const char *dishGetName(Dish dish);

/**
 * Returns the type of dish
 * @param dish The dish whose type is returned
 * @return
 * DISH_NUM_OF_TYPES if dish is NULL
 * The type of dish, if it's a valid Dish.
 */
DishType dishGetType(Dish dish);

/**
 * Returns the sweetness level of dish
 * @param dish The dish whose sweetness is returned
 * @return
 * 0 if dish is NULL
 * The sweetness of dish, if it's a valid Dish.
 */
int dishGetSweetness(Dish dish);

/**
 * Returns the sourness level of dish
 * @param dish The dish whose sourness is returned
 * @return
 * 0 if dish is NULL
 * The sourness of dish, if it's a valid Dish.
 */
int dishGetSourness(Dish dish);

/**
 * Returns the saltiness level of dish
 * @param dish The dish whose saltiness is returned
 * @return
 * 0 if dish is NULL
 * The saltiness of dish, if it's a valid Dish.
 */
int dishGetSaltiness(Dish dish);

/**
 * Checks if dish is edible
 * @param dish The dish to check for edibility
 * @return
 * false if Dish is NULL, or if it's inedible
 * true if Dish is edible.
 */
bool dishIsEdible(Dish dish);

#endif /* DISH_H_ */
